import random
from typing import List


class Generationsystem:
    def generation(self, length: int) -> List:
        result = []
        for i in range(length - 1):
            result.append(random.randint(1, 99))
            k = random.randint(1, 4)
            # print(k)
            if k == 1:
                result.append("+")
            elif k == 2:
                result.append("-")
            elif k == 3:
                result.append("x")
            else:  # k=4
                result.append("÷")
        result.append(random.randint(1, 99))
        return result

    def generation2(self, length: int) -> List:  # 生成整除式子,且不会同时出现2个连在一起的/
        flag = 0
        x = 0
        result = []
        for i in range(length):
            if flag == 1:
                flag = 0  # flag复位否则就会出现bug
                result.append(x)
                if i == length - 1:
                    return result
                k = random.randint(1, 3)
                if k == 1:
                    result.append("+")
                elif k == 2:
                    result.append("-")
                else:
                    result.append("x")
            else:
                if i == length - 1:
                    result.append(random.randint(1, 99))
                    return result
                k = random.randint(1, 4)
                if k == 1:
                    result.append(random.randint(1, 99))
                    result.append("+")
                elif k == 2:
                    result.append(random.randint(1, 99))
                    result.append("-")
                elif k == 3:
                    result.append(random.randint(1, 99))
                    result.append("x")
                else:
                    flag = 1
                    x = random.randint(1, 99)
                    n = random.randint(2, 9)
                    result.append(n * x)
                    result.append("÷")

    def generation_no_negative_numbers(self, length: int) -> List:  # 一个表达式中最多一个除法符号，并且最多一组括号对
        flag1 = 0  # 检查是否有除法符号
        x = 0
        result = []
        count = 2
        k = random.randint(1, 4)  # +,-,*,/
        if k == 4:
            x = random.randint(1, 99)
            n = random.randint(2, 9)
            result.append(n * x)
            result.append("÷")
            result.append(x)
            flag1 = 1
        else:
            result.append(random.randint(1, 99))
            if k == 3:
                result.append("x")
                result.append(random.randint(1, 9))
            elif k == 2:
                result.append("-")
                result.append(random.randint(1, 99))
            else:
                result.append("+")
                result.append(random.randint(1, 99))
        while (count < length):  # 当进入这个循环的时候，保证表达式是一个可以计算的算式
            result_str1 = [str(i) for i in result]
            result_str = ''.join(result_str1)
            if eval(result_str.replace("x", "*").replace("÷", "/")) < 0:
                result = self.generation_no_negative_numbers(count)
            count += 1
            if flag1 == 1:  # 出现过除法
                k = random.randint(1, 3)
                if k == 1:
                    result.append("+")
                    result.append(random.randint(1, 99))
                elif k == 2:
                    result.append("-")
                    result.append(random.randint(1, 99))
                else:
                    result.append("x")
                    result.append(random.randint(1, 9))
            else:
                k = random.randint(1, 3)
                if k == 1:
                    result.append("+")
                    result.append(random.randint(1, 99))
                elif k == 2:
                    result.append("-")
                    result.append(random.randint(1, 99))
                elif k == 3:
                    result.append("x")
                    result.append(random.randint(1, 99))
                else:
                    flag1 = 1
                    result.pop()
                    n = random.randint(1, 9)
                    x = random.randint(1, 99)
                    result.append(n * x)
                    result.append("÷")
                    result.append(x)
        result_str0 = [str(i) for i in result]
        result_str2 = ''.join(result_str0)
        if eval(result_str2.replace("x", "*").replace("÷", "/")) < 0:
            result = self.generation_no_negative_numbers(count)
        return result

    def generation3(self, length: int) -> List:  # 生成一个有括号的表达式但是不能保证其非负
        result = []
        result = self.generation_no_negative_numbers(length)
        i = random.randint(0, len(result) - 3)
        while i % 2 == 1:
            i = random.randint(0, len(result) - 3)
        result.insert(i, "(")
        j = random.randint(i + 4, len(result))
        while j % 2 == 1:
            j = random.randint(i + 4, len(result))
        result.insert(j, ")")
        result_str0 = [str(i) for i in result]
        result_str2 = ''.join(result_str0)
        if result[0] == "(" and result[-1] == ")":
            result = self.generation3(length)
        elif eval(result_str2.replace("x", "*").replace("÷", "/")) < 0:
            result = self.generation3(length)
        return result


# 基本上思路就是先做算术的确定，再确定数字最后输出
# 一年级的简单难度：10以内的加法，中等难度：20以内的加减法，困难难度：凑10练习
class Gradeone():
    # pro_har:1表示简单，2表示中等，3表示困难
    # type1表示填空题,2表示选择题,3表示判断题
    def __init__(self, pro_har: int, type: int):
        self.pro_har = pro_har
        self.score = 0
        self.type = type
        self.symbol = 0  # 存放符号，1表示加法,2表示减法
        self.num1 = 0  # 存放数字
        self.num2 = 0

    def symbolgeneration(self):
        if self.pro_har == 2:
            self.symbol = random.randint(1, 2)
        else:
            self.symbol = 1

    # 尽量保证a比b大
    def numbergeneration(self):
        if self.pro_har == 1:
            a = random.randint(1, 9)
            b = random.randint(1, 9)
        elif self.pro_har == 2:
            a = random.randint(1, 19)
            b = random.randint(1, 19)
            if self.symbol == 2:
                if a < b:
                    z = 0
                    z = a
                    a = b
                    b = z
        else:
            a = random.randint(1, 9)
            b = 10
        self.num1 = a
        self.num2 = b

    def checking(self):
        if not self.pro_har == 3:
            if self.symbol == 1:
                rightans = self.num1 + self.num2
                ans = input(str(self.num1) + "+" + str(self.num2) + "=")
                # 一个小bug,当输入的不是数字的时候会停止
                ans = int(ans)
                if ans == rightans:
                    print("很棒，你做对了这道题")
                    self.score += 3.33
                else:
                    print("噢哦，再接再厉")
            else:
                rightans = self.num1 - self.num2
                ans = input(str(self.num1) + "-" + str(self.num2) + "=")
                ans = int(ans)  # 一个小bug,当输入的不是数字的时候会停止
                if ans == rightans:
                    print("很棒，你做对了这道题")
                    self.score += 3.33
                else:
                    print("噢哦，再接再厉")
            return None
        else:
            rightans = 10 - self.num1
            ans = input("( )" + "+" + str(self.num1) + "=" + "10" + "   ()=")
            ans = int(ans)
            if ans == rightans:
                print("很棒，你做对了这道题")
                self.score += 3.33
            else:
                print("噢哦，再接再厉")
        return None

    # 测试的主函数，来测试该模块内的功能是否正确
    def mainfunc(self):
        print("每天30题的口算练习哦")
        get = input("如果准备好了就输入yes开始吧\n")
        while (not get == "yes"):
            get = input("输入yes开始\n")

        # 30道口算练习
        for i in range(30):
            print("第" + str(i + 1) + "道口算练习")
            self.symbolgeneration()
            self.numbergeneration()
            self.checking()
        final = int(self.score + 0.5)
        print("你的最终分数是" + str(final))
        if self.score >= 90:
            print("非常不错，你是数学天才小高斯")
        elif self.score >= 80:
            print("很好，你很有数学天赋，还可以再加把劲")
        elif self.score >= 70:
            print("多多努力你也会变得更强")
        else:
            print("看来要好好修炼计算能力了啊")
        return None

    # 接口创造，使得界面设计者可以使用我的类中的函数作为借口
    def get_ans(self):
        if not self.pro_har == 3:
            if self.symbol == 1:
                return self.num1 + self.num2
            else:
                return self.num1 - self.num2
        else:
            return 10 - self.num1

    # 接口创造，使得界面设计者可以使用我的接口
    def get_str(self):
        result = []
        if not self.pro_har == 3:
            result.append(str(self.num1))
            if self.symbol == 1:
                result.append("+")
            else:
                result.append("-")
            result.append(str(self.num2))
            return ''.join(result) + "="
        else:
            return "( )+" + str(self.num1) + "=10 ()="

    # 保持接口一致
    def calculationgeneration(self):
        self.symbolgeneration()
        self.numbergeneration()

    # 为了给不同的题型增加干扰项，加入了这个函数
    def createnumerals(self):
        self.calculationgeneration()
        ans = self.get_ans()
        if self.type == 2:  # 选择题
            l = [ans - 1, ans, ans + 1, ans + 2]
            random.shuffle(l)
            if ans == l[0]:
                xuanl = "A"
            elif ans == l[1]:
                xuanl = "B"
            elif ans == l[2]:
                xuanl = "C"
            else:
                xuanl = "D"
            return l, ans, xuanl
        elif self.type == 3:  # 判断题
            k = random.randint(1, 2)
            if k == 1:
                exc = ans
                xuanl = True
            else:
                exc = random.randint(1, 99)
                while exc == ans:
                    exc = random.randint(1, 99)
                xuanl = False
            return exc, ans, xuanl
        else:  # 简单填空题
            return None, ans, None

    # 保持接口一致
    def get_shuffle(self):
        (atk, ans, xuanl) = self.createnumerals()
        strin = self.get_str()
        return strin, ans, atk, xuanl


# 二年级的简单难度：10以内的乘除法，中等难度：10以内的连环乘除法，困难难度：带有括号的简单混合运算
class Gradetwo():
    # 同样在类中拥有难度选项，同时类中有result列表和正确答案结果
    # 加上了题型选项，可以通过初始化或者修改self.type得到
    def __init__(self, pro_har: int, type: int):
        self.pro_har = pro_har
        self.result = []
        self.rightans = 0
        self.score = 0
        self.type = type

    # 保持接口的一致，能够生成一个表达式
    def calculationgeneration(self):
        self.result = []  # debug
        if self.pro_har == 1:
            k = random.randint(1, 2)
            if k == 1:
                self.result.append(random.randint(1, 9))
                self.result.append("x")
                self.result.append(random.randint(1, 9))
            else:
                n = random.randint(1, 9)
                x = random.randint(1, 9)
                self.result.append(n * x)
                self.result.append("÷")
                self.result.append(x)
        elif self.pro_har == 2:
            self.result.append(random.randint(1, 9))
            self.result.append("x")
            self.result.append(random.randint(1, 9))
            self.result.append("x")
            self.result.append(random.randint(1, 9))
        else:
            k = random.randint(1, 2)
            k1 = random.randint(1, 2)
            k2 = random.randint(1, 2)
            if k == 1:  # x
                if k1 == 1:  # 第一个数变成括号
                    if k2 == 1:  # +
                        num1 = random.randint(5, 9)
                        num2 = random.randint(1, num1 - 1)
                        num3 = num1 - num2
                        num4 = random.randint(1, 9)
                        self.result.append("(")
                        self.result.append(num2)
                        self.result.append("+")
                        self.result.append(num3)
                        self.result.append(")")
                        self.result.append("x")
                        self.result.append(num4)
                    else:
                        num1 = random.randint(5, 9)
                        num2 = random.randint(num1 + 1, num1 + 9)
                        num3 = num2 - num1
                        num4 = random.randint(1, 9)
                        self.result.append("(")
                        self.result.append(num2)
                        self.result.append("-")
                        self.result.append(num3)
                        self.result.append(")")
                        self.result.append("x")
                        self.result.append(num4)
                else:
                    if k2 == 1:
                        num1 = random.randint(5, 9)
                        num2 = random.randint(1, num1 - 1)
                        num3 = num1 - num2
                        num4 = random.randint(1, 9)
                        self.result.append(num4)
                        self.result.append("x")
                        self.result.append("(")
                        self.result.append(num2)
                        self.result.append("+")
                        self.result.append(num3)
                        self.result.append(")")
                    else:
                        num1 = random.randint(5, 9)
                        num2 = random.randint(num1 + 1, num1 + 9)
                        num3 = num2 - num1
                        num4 = random.randint(1, 9)
                        self.result.append(num4)
                        self.result.append("x")
                        self.result.append("(")
                        self.result.append(num2)
                        self.result.append("-")
                        self.result.append(num3)
                        self.result.append(")")
            else:  # ÷
                if k1 == 1:
                    if k2 == 1:
                        n = random.randint(1, 9)
                        num3 = random.randint(1, 9)
                        numda = n * num3
                        num1 = random.randint(1, numda - 1)
                        num2 = numda - num1
                        self.result.append("(")
                        self.result.append(num1)
                        self.result.append("+")
                        self.result.append(num2)
                        self.result.append(")")
                        self.result.append("÷")
                        self.result.append(num3)
                    else:
                        n = random.randint(1, 9)
                        num3 = random.randint(1, 9)
                        numda = n * num3
                        num1 = random.randint(numda + 1, numda + 9)
                        num2 = num1 - numda
                        self.result.append("(")
                        self.result.append(num1)
                        self.result.append("-")
                        self.result.append(num2)
                        self.result.append(")")
                        self.result.append("÷")
                        self.result.append(num3)
                else:
                    if k2 == 1:
                        n = random.randint(1, 9)
                        num3 = random.randint(2, 9)
                        numda = n * num3
                        num1 = random.randint(1, num3 - 1)
                        num2 = num3 - num1
                        self.result.append(numda)
                        self.result.append("÷")
                        self.result.append("(")
                        self.result.append(num1)
                        self.result.append("+")
                        self.result.append(num2)
                        self.result.append(")")
                    else:
                        n = random.randint(1, 9)
                        num3 = random.randint(2, 9)
                        numda = n * num3
                        num1 = random.randint(num3 + 1, num3 + 9)
                        num2 = num1 - num3
                        self.result.append(numda)
                        self.result.append("÷")
                        self.result.append("(")
                        self.result.append(num1)
                        self.result.append("-")
                        self.result.append(num2)
                        self.result.append(")")

    # 保持接口一致，能够返回所生成的表达式的答案
    def get_ans(self):
        result_str0 = [str(i) for i in self.result]
        result_str2 = ''.join(result_str0)
        self.rightans = eval(result_str2.replace("x", "*").replace("÷", "//"))
        return self.rightans

    # 保持接口一致，能够返回所生成的表达式
    def get_str(self):
        result_str0 = [str(i) for i in self.result]
        result_str2 = ''.join(result_str0)
        result_str2 = result_str2 + "="
        return result_str2

    # 个人测试模块，测试自己的模块是否正确
    def checking(self):
        string = self.get_str()
        ans = input(string)
        ans = int(ans)
        if ans == self.rightans:
            self.score += 3.33
            print("Very Good!")
        else:
            print("Too bad!")

    def createnumerals(self):
        self.calculationgeneration()
        stri = self.get_str()
        ans = self.get_ans()
        if self.type == 2:  # 选择题
            l = [ans - 1, ans, ans + 1, ans + 2]
            random.shuffle(l)
            if l[0] == ans:
                xuanl = "A"
            elif l[1] == ans:
                xuanl = "B"
            elif l[2] == ans:
                xuanl = "C"
            else:
                xuanl = "D"
            return stri, ans, l, xuanl
        elif self.type == 3:  # 判断题
            k = random.randint(1, 2)
            if k == 1:
                exc = ans
                xuanl = True
            else:
                exc = random.randint(1, 99)
                while exc == ans:
                    exc = random.randint(1, 99)
                xuanl = False
            return stri, ans, exc, xuanl
        else:
            return stri, ans, None, None

    def get_shuffle(self):
        (stri, ans, etc, xuanl) = self.createnumerals()
        return stri, ans, etc, xuanl

    # 个人测试主函数，能够在终端运行
    def mainfunc(self):
        print("每天30题的口算练习哦")
        get = input("如果准备好了就输入yes开始吧\n")
        while (not get == "yes"):
            get = input("输入yes开始\n")

        for i in range(30):
            print("第" + str(i + 1) + "道口算练习")
            self.calculationgeneration()
            rightans = self.get_ans()
            self.checking()
            self.result = []
        final = int(self.score + 0.5)
        print("你的最终分数是" + str(final))
        if self.score >= 90:
            print("非常不错，你是数学天才小高斯")
        elif self.score >= 80:
            print("很好，你很有数学天赋，还可以再加把劲")
        elif self.score >= 70:
            print("多多努力你也会变得更强")
        else:
            print("看来要好好修炼计算能力了啊")
        return None


# 三年级的简单难度：两（三）位数乘（除）两位数；中等难度：不超过4个数字的加减乘除混合运算（不含括号）；
# 困难难度：加减乘除混合运算（含括号）
class Gradethree():
    # 与之前的模块接口保持一致
    def __init__(self, pro_hard: int, type: int):
        self.pro_har = pro_hard
        self.score = 0
        self.result = []
        self.rightans = 0
        self.generator = Generationsystem()
        self.type = type

    # 保持接口一致，能够实现计算题目的生成
    def calculationgeneration(self):
        self.result = []
        if self.pro_har == 1:
            k = random.randint(1, 2)
            if k == 1:
                self.result.append(random.randint(1, 99))
                self.result.append("x")
                self.result.append(random.randint(1, 9))
            else:
                n = random.randint(1, 9)
                x = random.randint(1, 99)
                self.result.append(n * x)
                self.result.append("÷")
                self.result.append(x)
        elif self.pro_har == 2:
            k = random.randint(2, 4)
            self.result = self.generator.generation_no_negative_numbers(k)
        else:
            k = random.randint(3, 4)
            self.result = self.generator.generation3(k)

    # 保持接口一致，实现得到生成表达式的结果的功能
    def get_ans(self):
        result_str0 = [str(i) for i in self.result]
        result_str2 = ''.join(result_str0)
        self.rightans = eval(result_str2.replace("x", "*").replace("÷", "//"))
        return self.rightans

    # 保持接口一致，实现得到生成的表达式的功能
    def get_str(self):
        result_str0 = [str(i) for i in self.result]
        result_str2 = ''.join(result_str0)
        result_str2 = result_str2 + "="
        return result_str2

    # 个人测试模块
    def checking(self):
        string = self.get_str()
        ans = input(string)
        ans = int(ans)
        if ans == self.rightans:
            self.score += 3.33
            print("Very Good!")
        else:
            print("Too bad!")

    # 保持接口一致
    def createnumerals(self):
        self.calculationgeneration()
        ans = self.get_ans()
        if self.type == 2:  # 选择题
            l = [ans - 1, ans, ans + 1, ans + 2]
            random.shuffle(l)
            if l[0] == ans:
                xuanl = "A"
            elif l[1] == ans:
                xuanl = "B"
            elif l[2] == ans:
                xuanl = "C"
            else:
                xuanl = "D"
            return ans, l, xuanl
        elif self.type == 3:  # 判断题
            k = random.randint(1, 2)
            if k == 1:
                etx = ans
                xuanl = True
            else:
                etx = random.randint(1, 99)
                while etx == ans:
                    etx = random.randint(1, 99)
                xuanl = False
            return ans, etx, xuanl
        else:
            return ans, None, None

    # 保持接口一致
    def get_shuffle(self):
        (ans, abx, xuanl) = self.createnumerals()
        strin = self.get_str()
        return strin, ans, abx, xuanl

    # 个人测试模块，测试模块功能是否正确
    def mainfunc(self):
        print("每天30题的口算练习哦")
        get = input("如果准备好了就输入yes开始吧\n")
        while (not get == "yes"):
            get = input("输入yes开始\n")

        for i in range(30):
            print("第" + str(i + 1) + "道口算练习")
            self.calculationgeneration()
            rightans = self.get_ans()
            self.checking()
            self.result = []
        final = int(self.score + 0.5)
        print("你的最终分数是" + str(final))
        if self.score >= 90:
            print("非常不错，你是数学天才小高斯")
        elif self.score >= 80:
            print("很好，你很有数学天赋，还可以再加把劲")
        elif self.score >= 70:
            print("多多努力你也会变得更强")
        else:
            print("看来要好好修炼计算能力了啊")
        return None


if __name__ == "__main__":
    print("欢迎使用家长帮出题系统，本系统提提供小学算术题的出题并改错。家长帮努力加载中")
    for grade in range(1,4):
    # 这边的想法是图形界面直接点击选择
        if grade == 1:
            for pro_hard in range(1,4):
                for pro_type in range(1,4):
                    for i in range(10):
                        gradeone = Gradeone(pro_hard,pro_type)
                        print(gradeone.get_shuffle())
        elif grade == 2:
            for pro_hard in range(1, 4):
                for pro_type in range(1, 4):
                    for i in range(10):
                        gradeone = Gradetwo(pro_hard, pro_type)
                        print(gradeone.get_shuffle())
        elif grade == 3:
            for pro_hard in range(1,4):
                for pro_type in range(1,4):
                    for i in range(10):
                        gradeone = Gradethree(pro_hard,pro_type)
